from werkzeug.security import generate_password_hash, check_password_hash
from flask import current_app
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy

db=SQLAlchemy()

#对重用的字段进行封装，不需要生成一张表
class BaseModel(object):
    create_time = db.Column(db.DateTime, default=datetime.now)
    update_time = db.Column(db.DateTime, default=datetime.now)
    isDelete = db.Column(db.Boolean, default=False)

#关系表：用户收藏新闻为多对多的关系
tb_news_collect = db.Table(
    'tb_news_collect',
    #在多个字段上设置primary_key=True，表示设置联合主键，这几个列的值全到一起，作主键
    db.Column('user_id', db.Integer, db.ForeignKey('user_info.id'), primary_key=True),
    db.Column('news_id', db.Integer, db.ForeignKey('news_info.id'), primary_key=True)
)
#关系表：用户关注作者为多对多的关系
tb_user_author = db.Table(
    'tb_user_author',
    db.Column('user_id', db.Integer, db.ForeignKey('user_info.id')),
    db.Column('author_id', db.Integer, db.ForeignKey('user_info.id'))
)
#新闻分类表
class NewsCategory(db.Model, BaseModel):
    __tablename__ = 'news_category'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(10))
    #关系属性：定义在一的端
    #
    #category=NewsCategory.query.get(1)
    #当进行上述查询时，是否查询此分类对应的新闻对象
    #如果不设置lazy='dynamic'则查询对应的新闻，即执行select * from news where category_id=id
    #如果设置lazy='dynamic'则不查询对应的新闻
    #作用：在获得分类对象时，可能不需要使用对应的新闻信息，如果查询了，则浪费了mysql的性能
    #通过category.news调用时会进行查询相应的新闻数据
    news = db.relationship('NewsInfo',
                           backref='category',
                           # backref=db.backref('category',lazy='dynamic'),
                           lazy='dynamic')

#新闻表
class NewsInfo(db.Model, BaseModel):
    __tablename__ = 'news_info'
    id = db.Column(db.Integer, primary_key=True)
    #图片：图片将被保存在磁盘上，表里存的是磁盘的目录
    pic = db.Column(db.String(50))
    title = db.Column(db.String(30))
    summary = db.Column(db.String(200))
    context = db.Column(db.Text)
    source = db.Column(db.String(20), default='')
    click_count = db.Column(db.Integer, default=0)
    comment_count = db.Column(db.Integer, default=0)
    status = db.Column(db.SmallInteger, default=1)
    reason=db.Column(db.String(100),default='')
    #关系外键：分类与新闻为1对多的关系，在新闻中定义外键，在分类中定义属性
    category_id = db.Column(db.Integer, db.ForeignKey('news_category.id'))
    #作者外键定义在多端，关系属性定义在一端
    user_id = db.Column(db.Integer, db.ForeignKey('user_info.id'))
    #关系属性：新闻的评论news.comments
    comments = db.relationship('NewsComment', backref='news', lazy='dynamic', order_by='NewsComment.id.desc()')

#用户类
class UserInfo(db.Model,BaseModel):
    __tablename__ = 'user_info'
    id = db.Column(db.Integer, primary_key=True)
    avatar = db.Column(db.String(50), default='user_pic.png')
    nick_name = db.Column(db.String(20))
    signature = db.Column(db.String(200))
    public_count = db.Column(db.Integer, default=0)
    follow_count = db.Column(db.Integer, default=0)
    mobile = db.Column(db.String(11))
    #加密后的密码
    password_hash = db.Column(db.String(200))
    gender = db.Column(db.Boolean, default=False)
    #是否管理员
    isAdmin = db.Column(db.Boolean, default=False)
    #关系属性：用户发布的新闻
    news = db.relationship('NewsInfo', backref='user', lazy='dynamic')
    #关系属性：用户发表的评论
    comments = db.relationship('NewsComment', backref='user', lazy='dynamic')
    #关系属性：用户收藏的新闻，多对多
    news_collect = db.relationship(
        'NewsInfo',
        #多对多的关系，外键定义在关系表中，需要通过secondary指定
        secondary=tb_news_collect,
        lazy='dynamic'
        #反向引用：新闻被哪些用户收藏
        #此处没有写backref表示：在业务中，不需要根据新闻找到收藏的用户，所以没写
    )
    #关系属性：用户关注作者
    #已经用户对象user
    #user.authors-->用户关注的作者对象
    #user.users-->用户的粉丝对象，即关注这个作者的用户对象
    authors = db.relationship(
        'UserInfo',
        #多对多的关系，需要指定关系表
        secondary=tb_user_author,
        #延迟加载
        lazy='dynamic',
        #反向引用
        backref=db.backref('users', lazy='dynamic'),
        #当自关联的多对多时，需要指定如下属性：primaryjoin，secondaryjoin
        #当调用user.authors时，user.id与关系表中的哪个字段进行对应
        primaryjoin=id == tb_user_author.c.user_id,
        #当调用user.users时，user.id与关系表中的哪个字段进行对应
        secondaryjoin=id == tb_user_author.c.author_id,
    )

    #user.password()==>user.password
    @property
    def password(self):
        pass
    #user.password=***==>user.password(***)
    @password.setter
    def password(self, pwd):
        self.password_hash = generate_password_hash(pwd)

    def check_pwd(self, pwd):
        return check_password_hash(self.password_hash, pwd)


class NewsComment(db.Model, BaseModel):
    __tablename__ = 'news_comment'
    id = db.Column(db.Integer, primary_key=True)
    news_id = db.Column(db.Integer, db.ForeignKey('news_info.id'))
    user_id = db.Column(db.Integer, db.ForeignKey('user_info.id'))
    like_count = db.Column(db.Integer, default=0)
    msg = db.Column(db.String(200))
    #关系外键：自关联
    comment_id = db.Column(db.Integer, db.ForeignKey('news_comment.id'))
    #关系属性:comment.comments==>当前评论的所有回复
    comments = db.relationship('NewsComment', lazy='dynamic')